#include "token.h"
#include "config.h"
#include <cjson/cJSON.h> //cjson
#include <curl/curl.h>   //libcurl
#include <curl/easy.h>
#include <stdio.h>
#include <stdlib.h> //free
#include <string.h> //strlen

//发送HTTP请求，并接收响应消息
char *token_send_request(char *ak, char *sk)
{
    //创建内存流
    //参数1：指向内存流中内容的指针
    //参数2：内存流中内容的大小
    char *response = NULL;
    size_t resplen = 0;
    FILE *fp = open_memstream(&response, &resplen);
    if (!fp)
    {
        perror("open_memstream");
        return NULL;
    }

    //初始化HTTP客户端
    //成功返回客户端句柄，失败返回NULL
    CURL *client = curl_easy_init();
    if (!client)
    {
        perror("curl_easy_init");
        fclose(fp);
        return NULL;
    }

    //自动分配缓冲区，将参数2中的内容写入缓冲区
    char *url = NULL;
    asprintf(&url,
             "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=%s&client_secret=%s", ak,
             sk);

    //设置HTTP请求地址
    curl_easy_setopt(client, CURLOPT_URL, url);

    //设置响应消息正文写入内存流中
    curl_easy_setopt(client, CURLOPT_WRITEDATA, fp);

    //发送HTTP请求
    CURLcode error = curl_easy_perform(client);
    if (error != CURLE_OK)
    {
        printf("send request error: %s\n", curl_easy_strerror(error));
        free(url);
        fclose(fp);
        free(response);
        curl_easy_cleanup(client);
        return NULL;
    }

    free(url);
    //关闭内存流，然后才能访问内存流中的内容
    fclose(fp);

    // printf("%s\n", response);

    //释放客户端占用内存
    curl_easy_cleanup(client);

    return response;
}

//解析响应报文
char *token_handle_response(char *response)
{
    char *retval = NULL;
    cJSON *obj = cJSON_Parse(response);
    if (obj)
    {
        cJSON *token = cJSON_GetObjectItem(obj, "access_token");
        if (token)
        {
            retval = strdup(token->valuestring);
        }
        cJSON_Delete(obj);
    }

    return retval;
}

char *get_token(void)
{
    char *retval = NULL;
    struct config cfg;

    if (parse_file("config.json", &cfg))
    {
        return retval;
    }

    char *response = token_send_request(cfg.api_key, cfg.secret_key);
    if (response)
    {
        retval = token_handle_response(response);
        //释放内存
        free(response);
    }

    return retval;
}
